package main

import "fmt"

type A struct {
	s string
}

// 在方法内返回局部变量的指针
func foo(s string) *A {
	a := new(A)
	a.s = s
	return a // 返回局部变量 a, a 会逃逸到堆
}

func main() {
	a := foo("hello")
	b := a.s + " world"
	c := b + "!"
	fmt.Println(c)
}

// go run -gcflags=-m yamls.go 或者 go build -gcflags=-m yamls.go
// Output:
// # command-line-arguments
// ./yamls.go:10:6: can inline foo
// ./yamls.go:17:10: inlining call to foo
// ./yamls.go:20:13: inlining call to fmt.Println
// ./yamls.go:10:10: leaking param: s
// ./yamls.go:11:10: new(A) escapes to heap
// ./yamls.go:17:10: new(A) does not escape
// ./yamls.go:18:11: a.s + " world" does not escape
// ./yamls.go:19:9: b + "!" escapes to heap
// ./yamls.go:20:13: c escapes to heap
// ./yamls.go:20:13: []interface {} literal does not escape
// <autogenerated>:1: .this does not escape
// <autogenerated>:1: .this does not escape
// hello world!
//
//
// ./yamls.go:11:10: new(A) escapes to heap 说明 new(A) 逃逸了。
// ./yamls.go:18:11: a.s + " world" does not escape 说明 b 变量没有逃逸，因为它只在方法内存在，会在方法结束时被回收。
// ./yamls.go:19:9: b + "!" escapes to heap 说明 c 变量逃逸，通过 fmt.Println(a ...interface{}) 打印的变量，都会发生逃逸，
// 因为 fmt.Println(a ...interface{}) 在编译期间很难确定 a 的类型。